﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Net;
using System.Threading;
using System.Linq;
using System.Windows;

namespace EbbinghausWord.BLL
{
    /// <summary>
    /// 发音管理
    /// </summary>
    public class VoiceManager
    {
        #region private field

        private static IsolatedStorageFile _isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication();
        private static List<string> _haveDownloadVoiceWords = null;
        //private static int _haveDownloadVoiceWordsCount
        #endregion

        /// <summary>
        /// 初始化已经下载的单词发音文件
        /// </summary>
        public static void InitHaveDownloadVoiceWord()
        {
            _haveDownloadVoiceWords = _isolatedStorageFile.GetFileNames("voice\\*.mp3")
                .Select(x => x.Substring(0, x.Length - 4)).ToList();
        }

        /// <summary>
        /// 异步获得单词发音
        /// </summary>
        /// <param name="english"></param>
        public void GetVoiceAsync(string english)
        {
            //文件是否存在，如果存在
            if (IsFileExist(english))
            {
                OnGetVoice(english);
            }
            else
            {
                try
                {
                    //如果音乐文件不存在，则下载
                    var client = new WebClient();
                    client.OpenReadCompleted += ClientOpenReadCompleted;
                    client.OpenReadAsync(new Uri("http://dict.youdao.com/dictvoice?audio=" + english,
                        UriKind.Absolute), english);
                }
                catch (Exception ex)
                {
                    OnGetVoiceFailed(english);
                }
            }
        }

        /// <summary>
        /// 发送获得单词发音的事件
        /// </summary>
        /// <param name="english"></param>
        private void OnGetVoice(string english)
        {
            if (GetVoiceCompleted != null)
            {
                using (var stream = _isolatedStorageFile.OpenFile(CreateFilePath(english), FileMode.Open,
                    FileAccess.Read))
                {
                    GetVoiceCompleted(this, new VoiceEventArgs()
                    {
                        VoiceFileStream = stream,
                    });
                }
            }
        }

        /// <summary>
        /// 发送获取发音失败的事件
        /// </summary>
        /// <param name="errorWord"></param>
        private void OnGetVoiceFailed(string errorWord)
        {
            if (GetVoiceFailed != null)
            {
                GetVoiceFailed(this, new VoiceFailedEventArgs() { ErrorWord = errorWord });
            }
        }

        /// <summary>
        /// 生成声音文件路径
        /// </summary>
        /// <param name="english"></param>
        /// <returns></returns>
        private static string CreateFilePath(string english)
        {
            return SystemConfig.VoiceFilePath + @"/" + english + ".mp3";
        }

        /// <summary>
        /// 获取单词发音完成
        /// </summary>
        public event EventHandler<VoiceEventArgs> GetVoiceCompleted;

        /// <summary>
        /// 下载单词发音失败
        /// </summary>
        public event EventHandler<VoiceFailedEventArgs> GetVoiceFailed;

        /// <summary>
        /// 声音文件是否存在
        /// </summary>
        /// <param name="english"></param>
        /// <returns></returns>
        public static bool IsFileExist(string english)
        {
            return _haveDownloadVoiceWords.Contains(english) || _isolatedStorageFile.FileExists(CreateFilePath(english));
        }

        /// <summary>
        /// 删除指定单词的发音文件
        /// </summary>
        /// <param name="english"></param>
        public static void DeleteVoiceFile(string english)
        {
            if (IsFileExist(english))
            {
                _isolatedStorageFile.DeleteFile(CreateFilePath(english));
                _haveDownloadVoiceWords.Remove(english);
            }
        }

        void ClientOpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            var english = e.UserState.ToString();

            try
            {
                var read = e.Result;
                var length = e.Result.Length;
                var byData = new byte[length];

                using (var write = _isolatedStorageFile.OpenFile(CreateFilePath(english), FileMode.Create,
                                                            FileAccess.ReadWrite))
                {
                    while (write.Length < read.Length)
                    {
                        read.Read(byData, 0, (int)length);
                        write.Write(byData, 0, (int)length);
                    }
                }

                _haveDownloadVoiceWords.Add(english);
                OnGetVoice(english);
            }
            catch (Exception)
            {
                OnGetVoiceFailed(english);
            }
        }

        /// <summary>
        /// 初始化发音文件 的文件夹
        /// </summary>
        public static void InitVoiceDirectory()
        {
            if (!_isolatedStorageFile.DirectoryExists(SystemConfig.VoiceFilePath))
            {
                _isolatedStorageFile.CreateDirectory(SystemConfig.VoiceFilePath);
            }
        }

        #region 多文件下载

        private static int _downloadIndex = 0;
        private static int _wordCount = WordBookManager.WordBook.GroupBy(x => x.English.ToLower()).Count();
        private bool _isBreakDownload = false;

        /// <summary>
        /// 批量下载
        /// </summary>
        private void DownloadVoice()
        {
            var client = new WebClient();
            var voiceManager = new VoiceManager();
            var resetEvent = new AutoResetEvent(false);

            voiceManager.GetVoiceCompleted += (s, ex) =>
                                                  {
                                                      //通知下载进度变更
                                                      if (MuliDownloadPercentaging != null)
                                                      {

                                                          MuliDownloadPercentaging(null, new MuliDownloadPercentageEventArgs()
                                                                                             {
                                                                                                 HaveDownloadCount = _downloadIndex,
                                                                                             });
                                                          //{
                                                          //    HaveDownloadCount = VoiceManager.GetVoiceFileCount(),
                                                          //    TotalCount = _wordCount
                                                          //});
                                                      }

                                                      //通知事件放行
                                                      resetEvent.Set();
                                                  };

            voiceManager.GetVoiceFailed += (s, ex) =>
                                               {

                                                   //MessageBox.Show("error : " + ex.ErrorWord)
                                               };
            for (; ; )
            {
                //获取单词
                if (_downloadIndex >= _wordCount)
                {
                    //抛出下载完成的事件
                    if (MultiDownloadVoiceCompleted != null)
                    {
                        MultiDownloadVoiceCompleted(this, null);
                    }

                    break;
                }

                //用户是否停止下载
                if (_isBreakDownload)
                {
                    break;
                }

                var english = WordBookManager.WordBook[_downloadIndex++].English;

                //下载文件
                voiceManager.GetVoiceAsync(english);
                resetEvent.WaitOne(5000);
            }
        }

        /// <summary>
        /// 开始下载声音文件
        /// </summary>
        public void StartDownloadVoice()
        {
            _isBreakDownload = false;
            _downloadIndex = 0;
            new Thread(DownloadVoice).Start();
        }

        /// <summary>
        /// 停止下载发音文件
        /// </summary>
        public void StopDownloadVoice()
        {
            _isBreakDownload = true;
        }

        /// <summary>
        /// 多文件下载的下载进度
        /// </summary>
        public event EventHandler<MuliDownloadPercentageEventArgs> MuliDownloadPercentaging;

        /// <summary>
        /// 多文件下载的事件
        /// </summary>
        public event EventHandler<EventArgs> MultiDownloadVoiceCompleted;

        /// <summary>
        /// 获得发音文件数量
        /// </summary>
        /// <returns></returns>
        public static int GetVoiceFileCount()
        {
            //var voiceFiles = _isolatedStorageFile.GetFileNames("voice\\*.mp3")
            //    .ToList();
            //return voiceFiles.Count();
            return _haveDownloadVoiceWords.Count;
        }

        /// <summary>
        /// 获得需要下载的发音文件数量
        /// </summary>
        /// <returns></returns>
        public static int GetTotalCount()
        {
            return _wordCount;
        }

        #endregion
    }

    /// <summary>
    /// 单词发音的事件参数类
    /// </summary>
    public class VoiceEventArgs : EventArgs
    {
        public Stream VoiceFileStream { get; set; }
    }


    /// <summary>
    /// 单词发音 获取失败的 事件类
    /// </summary>
    public class VoiceFailedEventArgs : EventArgs
    {
        public string ErrorWord { get; set; }
    }


    /// <summary>
    /// 多文件下载的参数
    /// </summary>
    public class MuliDownloadPercentageEventArgs : EventArgs
    {
        /// <summary>
        /// 已经下载的文件数量
        /// </summary>
        public int HaveDownloadCount { get; set; }

        /// <summary>
        /// 总共需要下载的文件数量
        /// </summary>
        public int TotalCount { get; set; }
    }
}
